import hashlib
import json
import random
import time

import execjs
import pymongo
import redis
import requests
from retrying import retry


class JD:
    def __init__(self):
        self.mongo_client = pymongo.MongoClient(host='175.178.162.117', port=27017, username="root",
                                                password="H5rOx4dG")
        self.collection = self.mongo_client['py_spider']['jd_shop_info']
        self.redis_client = redis.Redis(host='192.168.80.3', port=6379, db=1)
        self.headers = {
            "authority": "api.m.jd.com",
            "accept": "application/json, text/plain, */*",
            "accept-language": "zh-CN,zh;q=0.9",
            "cache-control": "no-cache",
            "origin": "https://union.jd.com",
            "pragma": "no-cache",
            "referer": "https://union.jd.com/",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
            "x-referer-page": "https://union.jd.com/proManager/index",
            "x-rp-client": "h5_1.0.0"
        }
        self.cookies = {
            "__jdv": "95931165|direct|-|none|-|1712030110101",
            "__jdu": "1712030110101289861918",
            "mba_muid": "1712030110101289861918",
            "shshshfpa": "2e100608-92d8-7467-8126-e8850b543e6e-1711367190",
            "shshshfpx": "2e100608-92d8-7467-8126-e8850b543e6e-1711367190",
            "thor": "9CBBFE857495DDABD9EAD97760652A06BCA753B1D5E51C5EAC1578C31E14D53A6852BC37A0E0AB81F9097A5EA1DC401BD91B9C000AA3B490F09454B4770369970E995BB5A3CE0F7D17B4962222AAA4946C9EAE1D2EB835407A046F6DA365CE24F62D6E54D73EDC7CAAFA24F0846A8150598805A170D716D6357B3BC7DF9D324C64BC06CC9CF72D68A50761DC5F7BEA22F0C2795E65C92DA2D887D88C0E840CB3",
            "flash": "2_4Xto4j8WliOVOU4MtVFTGev2KmaMCMfpHrY7iFMFE5PC9HKk1wwGnMRmMzrS3UgbgY5WMSQDtb-EX4O3ycRXHUaVgOFnaDEiKtKIfrSixok*",
            "pinId": "XQ52sNdRavS-PdmM4M3eRLV9-x-f3wj7",
            "pin": "jd_4b6e03ee74e6f",
            "unick": "jd_4b6e03ee74e6f",
            "ceshi3.com": "000",
            "_tp": "4D%2F%2BO65W5ovxPpYdjmEP19qX6nKCaymCFvbbjn7DFnA%3D",
            "logining": "1",
            "_pst": "jd_4b6e03ee74e6f",
            "mba_sid": "1712067042584892315432555714.2",
            "__jd_ref_cls": "LoginDisposition_Go",
            "wlfstk_smdl": "wn3b4i7pp7locvvrtymn4lioxunjf86c",
            "3AB9D23F7A4B3C9B": "D3W3OEZEOJRV3RA3RK7F5OBW4PXQEC7DKB2LVHILSINEBPVJEDZ5WBYFDUJV6QN2Z7V7KODMR5L6B75JZ6X225KT74",
            "__jda": "209449046.1712030110101289861918.1712030110.1712030110.1712066847.2",
            "__jdc": "209449046",
            "3AB9D23F7A4B3CSS": "jdd03D3W3OEZEOJRV3RA3RK7F5OBW4PXQEC7DKB2LVHILSINEBPVJEDZ5WBYFDUJV6QN2Z7V7KODMR5L6B75JZ6X225KT74AAAAMOT4TBL3IAAAAACO74BCPJR5WWKQX",
            "shshshfpb": "BApXe-mMunOtA5qgYYJ-a0zPvgfKwko-0BlN3dr949xJ1MqtfHIC2",
            "__jdb": "209449046.25.1712030110101289861918|2.1712066847",
            "RT": "\"z=1&dm=jd.com&si=5pr7mjwwrr3&ss=luigiba5&sl=6&tt=6d5&ld=2imz\""
        }

        self.url = "https://api.m.jd.com/api"

        self.js = execjs.compile(open('京东.js', encoding='utf-8').read())

    @retry(wait_random_min=1000, wait_random_max=5000, stop_max_attempt_number=5)
    def get_data(self, page):
        body = {
            "funName": "search",
            "version": "v3",
            "source": 20310,
            "param": {
                "pageNo": page,
                "pageSize": 60,
                "searchUUID": "96951a86e3864f958a3c0dfb5a91f42c",
                "bonusIds": "",
                "category1": "",
                "category2": "",
                "category3": "",
                "deliveryType": "",
                "wlRate": "",
                "maxWlRate": "",
                "fromPrice": "",
                "toPrice": "",
                "hasCoupon": "",
                "isHot": "",
                "isNeedPreSale": "",
                "isPinGou": "",
                "isZY": "",
                "isCare": "",
                "lock": "",
                "orientationFlag": "",
                "sort": "",
                "sortName": "",
                "keyWord": "",
                "searchType": "st3",
                "keywordType": "kt0"
            },
            "clientPageId": "jingfen_pc"
        }
        p = self.js.call('get_data', body)
        # print(p['h5st'])
        params = {
            "functionId": "unionSearch",
            "appid": "unionpc",
            "_": str(int(time.time() * 1000)),
            "loginType": "3",
            "uuid": "1712030110101289861918",
            "x-api-eid-token": "jdd03D3W3OEZEOJRV3RA3RK7F5OBW4PXQEC7DKB2LVHILSINEBPVJEDZ5WBYFDUJV6QN2Z7V7KODMR5L6B75JZ6X225KT74AAAAMOW6PZDKYAAAAAD4MULJNT5Q3VGQX",
            "h5st": p['h5st'],
            "body": json.dumps(body, ensure_ascii=False, separators=(",", ":"))
        }
        response = requests.get(self.url, headers=self.headers, cookies=self.cookies, params=params)
        print(f"获取第{page}页数据：", response.status_code)
        if response.status_code == 200:
            res = response.json()
            if res['code'] != 200:
                print(res)
                return
            for data in res['data']['skuPage']['result']:
                item = dict()
                item['shopName'] = data['skuName']
                item['price'] = data['price']
                item['storeName'] = data['venderName']
                item['goodComments'] = data['goodComments']
                # 将传递过来的item数据转为字符串并加密成md5数
                hash_value = hashlib.md5(json.dumps(item, ensure_ascii=False).encode()).hexdigest()
                # redis去重，不存在才入库
                if self.redis_client.sadd("jd_shop_filter", hash_value) != 0:
                    self.collection.insert_one(item)
                    print("入库成功：", item)
                else:
                    print("数据重复：", item['shopName'])
        else:
            print(response.text)
            print(f"访问失败，第{page}页")
            raise requests.exceptions.ReadTimeout('数据获取出错')

    def __del__(self):
        self.mongo_client.close()
        self.redis_client.close()


if __name__ == '__main__':
    jd = JD()
    for i in range(1, 50):
        jd.get_data(i)
        time.sleep(random.randint(1, 3))
